// 代理类封装了MqttSubConnection作为其委托类，实现所有上层逻辑
#ifndef MqttConnectionClass
#define MqttConnectionClass
#include "MqttSubConnection.hpp"
#include <sys/time.h>
#include "MqttOnMessageCallback.hpp"
#include <unordered_set>
#include "lib/sole/sole.hpp"
#define MQTT_PREFIX "MQTT_"
#define ifprintf \
    if (false)   \
    printf
class MqttConnection
{
private:
    MqttSubConnection *connection;
    std::string address, clientId, userName, password, name;
    int port;
    bool enable = true;
    std::recursive_mutex subMutex;
    // 加锁
    std::unordered_map<std::string, std::unordered_set<MqttOnMessageCallback *>> topicCallbackMap;
    std::unordered_map<std::string, MqttConnection *> *nameConnectionMap = nullptr;
    void inline tryEmplace(std::string topic, MqttOnMessageCallback *callback);
    bool inline tryRemove(std::string topic, MqttOnMessageCallback *callback);
    bool connect();

public:
    bool connected = false;
    bool looping = false;
    std::string uuid;
    std::string remarks;
    static inline long getCurrentMs();
    virtual ~MqttConnection();
    MqttConnection(std::unordered_map<std::string, MqttConnection *> *nameConnectionMap,
                   const std::string &name,
                   const std::string &address,
                   bool enable = false,
                   int port = 1883,
                   const std::string &userName = "",
                   const std::string &password = "");
    std::string getClientId();
    bool subscribe(const std::string &topic, MqttOnMessageCallback *callback);
    void unsubscribe(std::string topic, MqttOnMessageCallback *callback);
    bool publish(const std::string &topic, const std::string &data);
    static void loop(MqttConnection *p);
    void setAddress(const std::string &address, bool autoConnect = false);
    void setPort(int port, bool autoConnect = false);
    void setUserName(const std::string &userName, bool autoConnect = false);
    void setEnable(bool enable);
    void setPassword(const std::string &password, bool autoConnect = false);
    bool setName(const std::string &name);
    std::string getName();
    std::string getStatus();
    std::string getAddress();
    int getPort();
    bool isEnable();
    std::string getUserName();
    std::string getPassword();
};
#endif